package cz.martindobias.aladin.xpathtest;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
import uk.co.flamingpenguin.jewel.cli.ArgumentValidationException;
import uk.co.flamingpenguin.jewel.cli.Cli;
import uk.co.flamingpenguin.jewel.cli.CliFactory;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;

public class Test {

    public static void main(String[] args) {
        try {
            Cli<CommandLineArguments> cli = CliFactory.createCli(CommandLineArguments.class);
            CommandLineArguments arguments = cli.parseArguments(args);

            if(!arguments.isURL() && !arguments.isLocalFile()) {
                System.err.println("One of URL or local file has to be specified");
                System.err.println(cli.getHelpMessage());
            } else {
                String source;
                if(arguments.isLocalFile()) {
                    source = Test.openFile(arguments.getLocalFile());
                } else {
                    source = Test.openURL(arguments.getURL());
                }

                Writer output = null;
                if(arguments.isSaveFile()) {
                    try {
                        output = new FileWriter(arguments.getSaveFile());
                    } catch(IOException e) {
                        System.err.println("Error opening output file");
                    }
                }

                Tidy tidy = new Tidy();
                //tidy.setShowErrors(0);
                //tidy.setShowWarnings(false);
                tidy.setQuiet(true);
                //tidy.setOnlyErrors(true);
                tidy.setTrimEmptyElements(false);
                StringReader sr = new StringReader(source);
                Document doc = tidy.parseDOM(sr, output);
                sr.close();

                if(output != null) {
                    try {
                        output.close();
                    } catch(IOException e) {
                        System.err.println("Error closing output file");
                    }
                }

                XPath xpath = XPathFactory.newInstance().newXPath();
                String command;
                InputStreamReader stream = new InputStreamReader(System.in);
                BufferedReader reader = new BufferedReader(stream);
                try {
                    do {
                        command = reader.readLine();
                        if(command != null && !"".equals(command)) {
                            try {
                                NodeList nodes = (NodeList) xpath.evaluate(command, doc, XPathConstants.NODESET);
                                System.out.println("list: " + nodes.getLength());
                                for(int i = 0; i < nodes.getLength(); i++) {
                                    System.out.println(nodes.item(i).getNodeName() + ": " + nodes.item(i).getNodeValue() + ": " + nodes.item(i).getTextContent());
                                }
                            } catch(XPathExpressionException e) {
                                e.printStackTrace();
                            }
                        }
                    } while(command != null && !"".equals(command));
                } catch(IOException e) {
                    System.err.println("Error reading command line");
                    e.printStackTrace();
                } finally {
                    try {
                        reader.close();
                        stream.close();
                    } catch(IOException e) {
                        System.err.println("Error closing command line access");
                        e.printStackTrace();
                    }
                }
            }
        } catch(ArgumentValidationException e) {
            System.err.println(e.getLocalizedMessage());
        }
    }

    private static String openFile(String file) {
        String content = null;
        FileInputStream is = null;

        try {
            is = new FileInputStream(file);
            content = Test.readSource(is);
        } catch(IOException e) {
            System.err.println("Could not access file: " + file);
            e.printStackTrace();
        } finally {
            try {
                if(is != null) {
                    is.close();
                }
            } catch(IOException e) {
                System.err.println("Error closing file");
                e.printStackTrace();
            }
        }

        return content;
    }

    private static String openURL(String url) {
        String content = null;
        InputStream is = null;

        try {
            URLConnection connection = new URL(url).openConnection();
            connection.connect();
            is = connection.getInputStream();
            content = Test.readSource(is);
        } catch(IOException e) {
            System.err.println("Could not access remote resource: " + url);
            e.printStackTrace();
        } finally {
            try {
                if(is != null) {
                    is.close();
                }
            } catch(IOException e) {
                System.err.println("Error closing remote stream");
                e.printStackTrace();
            }
        }

        return content;
    }

    private static String readSource(InputStream is) throws IOException {
        String content = null;
        BufferedInputStream bis = null;

        try {
            bis = new BufferedInputStream(is);
            StringBuilder builder = new StringBuilder();
            byte[] buffer = new byte[1024];
            int c;
            do {
                c = bis.read(buffer);
                if(c > 0) {
                    builder.append(new String(buffer, 0, c, "UTF-8"));
                }
            } while(c != -1);
            content = builder.toString();
        } finally {
            try {
                if(bis != null) {
                    bis.close();
                }
            } catch(IOException e) {
                System.err.println("Error closing data stream");
                e.printStackTrace();
            }
        }

        return content;
    }

}
